using System;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using MySql.Data.MySqlClient;
using System.Net;
using Aliyun.OSS;


namespace FileChangeNotifier 
{

    public partial class frmNotifier : Form
    {
        // For MySQL connection
        private MySqlConnection m_connection;

        string m_webstring = @"https://api.github.wakeupsoft.com/api/facial/createrecord";
        //string m_webstring = @"http://localhost:4000/facial/createrecord";

        static object Lock = new object();
        private StringBuilder m_Sb;
        private bool m_bDirty;
        private System.IO.FileSystemWatcher m_Watcher;
        private bool m_bIsWatching;
        private StringCollection m_strCol = new StringCollection();

        public frmNotifier()
        {
            InitializeComponent();
            m_Sb = new StringBuilder();
            m_bDirty = false;
            m_bIsWatching = false;
        }

        private void frmNotifier_FormClosed(object sender, FormClosedEventArgs e)
        {

        }

        private bool OpenDBConnection(string server, string database, string uid, string password)
        {
            /*
            server = txtDBServer.Text;
            database = txtDBName.Text;
            uid = txtDBUser.Text;
            password = txtDBPwd.Text;
            */

            string connectionString;
            connectionString = "SERVER=" + server + ";" + "DATABASE=" +
            database + ";" + "UID=" + uid + ";" + "PASSWORD=" + password + ";";

            m_connection = new MySqlConnection(connectionString);

            try
            {
                m_connection.Open();
            }
            catch (MySqlException ex)
            {
                //When handling errors, you can your application's response based 
                //on the error number.
                //The two most common error numbers when connecting are as follows:
                //0: Cannot connect to server.
                //1045: Invalid user name and/or password.
                switch (ex.Number)
                {
                    case 0:
                        MessageBox.Show("Cannot connect to server.  Contact administrator");
                        break;

                    case 1045:
                        MessageBox.Show("Invalid username/password, please try again");
                        break;
                    default:
                        MessageBox.Show(ex.Message);
                        break;
                }
                return false;
                //btnWatchFile.Enabled = false;
            }
            return true;
        }

        private void CloseDBConnection()
        {
            try
            {
                if (m_connection != null)
                    m_connection.Close();
            }
            catch (MySqlException ex)
            {
                MessageBox.Show(ex.Message);
            }
            m_connection = null;
        }

        private bool InsertDBFacialData(string device, char type, string user, string filename, string datetime)
        {
            try
            {
                string query = String.Format("INSERT INTO facial_record (device, type, user, filename, date_created) VALUES(\"{0}\", \"{1}\", \"{2}\", \"{3}\",\"{4}\")", device, type, user, filename, datetime);
                //m_strCol.Add(query);
                //create command and assign the query and connection from the constructor
                MySqlCommand cmd = new MySqlCommand(query, m_connection);
                //Execute command
                cmd.ExecuteNonQuery();
            }
            catch (MySqlException ex)
            {
                MessageBox.Show(ex.Message);
            }
            //statement = "filename=" + filename + " " + "type=" + type + " " + "user=" + user + " " + "UTC=" + datetimeList[0];
            //m_strCol.Add(statement);
            return true;
        }

        private string PostFacialRecord(string uri, string device, string usertype, string username, string filename, string created_date)
        {
            string response;
            using (WebClient client = new WebClient())
            {
                String s = String.Format("\"device\":\"{0}\", \"type\":\"{1}\", \"username\":\"{2}\", \"filename\":\"{3}\", \"date_created\":\"{4}\" ", device, usertype, username, filename, created_date);
                s = "{" + s + "}";
                client.Headers[HttpRequestHeader.ContentType] = "application/json";
                response = client.UploadString(uri, s);
                /*
                response = client.UploadString(uri, String.Format("{ \"device\":\"{0}\", \"type\":\"{1}\", \"username\":\"{2}\", \"filename\":\"{3}\", \"date_created\":\"{4}\"	} ", 
                    device, usertype, filename, created_date ) );
                */
            }
            return response;
        }
        private bool UploadAliyunOSS(string filename, Stream filePathToUpload)
        {
            OssClient client = new OssClient("oss-cn-hongkong.aliyuncs.com", "LTAI51AlF1Uv0X4O", "NwEvwfogr7PeCPD2zZ148RfJelgudh");

            client.PutObject("facialrecord", filename, filePathToUpload);
            return true;
        }

        private bool HttpInsertFacialRecord(string device, char type, string user, string filename, string datetime)
        {
            string word = "any word";
            string SDate = "2014-09-05";
            string EDate = "2015-03-05";
            string token = "TOKEN";
            string MoodysWebstring = @"http://www.abc.com/search?word=" + word + "&SDate=" + SDate + "&EDate=" + EDate + "&token=" + token;
            Uri MoodysWebAddress = new Uri(MoodysWebstring);
            HttpWebRequest request = WebRequest.Create(MoodysWebAddress) as HttpWebRequest;
            request.Method = "GET";
            request.ContentType = "text/xml";
            string results = string.Empty;
            HttpWebResponse response;
            using (response = request.GetResponse() as HttpWebResponse)
            {
                StreamReader reader = new StreamReader(response.GetResponseStream());
                results = reader.ReadToEnd();
            }
            return true;
        }

private void btnWatchFile_Click(object sender, EventArgs e)
        {
            if (m_bIsWatching)
            {
                CloseDBConnection();
                m_strCol.Add("Closed database");

                m_bIsWatching = false;
                m_Watcher.EnableRaisingEvents = false;
                m_Watcher.Dispose();
                btnWatchFile.BackColor = Color.Transparent;
                btnWatchFile.Text = "Start Watching";
                
            }
            else
            {
                if ( OpenDBConnection(txtDBServer.Text, txtDBName.Text, txtDBUser.Text, txtDBPwd.Text) )
                {
                    m_strCol.Add( String.Format("Connected to server: {0}, database: {1}", txtDBServer.Text, txtDBName.Text) );
                }
                else
                {
                    m_strCol.Add( String.Format("Failed to connect server: {0}, database: {1}", txtDBServer.Text, txtDBName.Text) );
                    m_connection = null;
                }
            
                m_bIsWatching = true;
                btnWatchFile.BackColor = Color.LightGreen;
                btnWatchFile.Text = "Stop Watching";

                try
                {
                    m_Watcher = new System.IO.FileSystemWatcher();
                    if (rdbDir.Checked)
                    {
                        m_Watcher.Filter = "*.jpg*";
                        m_Watcher.Path = txtFile.Text + "\\";
                    }
                    else
                    {
                        m_Watcher.Filter = txtFile.Text.Substring(txtFile.Text.LastIndexOf('\\') + 1);
                        m_Watcher.Path = txtFile.Text.Substring(0, txtFile.Text.Length - m_Watcher.Filter.Length);
                    }

                    if (chkSubFolder.Checked)
                    {
                        m_Watcher.IncludeSubdirectories = true;
                    }

                    m_Watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
                                         | NotifyFilters.FileName | NotifyFilters.DirectoryName;
                   // m_Watcher.Changed += new FileSystemEventHandler(OnChanged);
                    m_Watcher.Created += new FileSystemEventHandler(OnChanged);
                  //  m_Watcher.Deleted += new FileSystemEventHandler(OnChanged);
                  //  m_Watcher.Renamed += new RenamedEventHandler(OnRenamed);
                    m_Watcher.EnableRaisingEvents = true;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
            m_bDirty = true;
        }

        private void OnChanged(object sender, FileSystemEventArgs e)
        {
            lock (Lock)
            {
                string statement = e.FullPath + " " + e.ChangeType.ToString() + " " + DateTime.Now.ToString();
                m_strCol.Add(statement);

                if ("Created" == e.ChangeType.ToString())
                {
                    string filename = Path.GetFileName(e.FullPath);

                    char[] filter = { '_', '.' };
                    string[] strList = filename.Split(filter);
                    char type = strList[0][0];
                    string user = strList[0].Substring(1);
                    string[] datetimeList = DateTime.UtcNow.GetDateTimeFormats('s');

                    if (m_connection != null)
                    {
                        if (!InsertDBFacialData(txtDeviceName.Text, type, user, filename, datetimeList[0]))
                            m_strCol.Add("Failed to insert to DB, " + filename);
                    }

                    if (UploadAliyunOSS(filename, new FileStream(e.FullPath, FileMode.Open)))
                    {
                        string response = PostFacialRecord(m_webstring, txtDeviceName.Text, String.Format("{0}", type), user, filename, datetimeList[0]);
                        m_strCol.Add(m_webstring + " response: " + response);
                    }
                    /*
                    var response = PostFacialRecord(m_webstring, new NameValueCollection() {
                        { "device", device },
                        { "type", String.Format("%c", type) },
                        { "user", user },
                        { "filename", filename },
                        { "date_created", datetimeList[0] }
                    });
                    */

                }

                m_bDirty = true;

                //m_Sb.AppendLine(Environment.NewLine);
                //m_Sb.Remove(0, m_Sb.Length);
                /*
                if (m_Sb.Length > 0)
                    m_Sb.Append("\n");
                m_Sb.Append(e.FullPath);
                m_Sb.Append(" ");
                m_Sb.Append(e.ChangeType.ToString());
                m_Sb.Append("    ");
                m_Sb.Append(DateTime.Now.ToString());
                */
            }
        }

        private void OnRenamed(object sender, RenamedEventArgs e)
        {
            lock (Lock)
            {
                string str = e.OldFullPath + " " + e.ChangeType.ToString() + " to " + e.Name + "  " + DateTime.Now.ToString();
                m_strCol.Add(str);
                m_bDirty = true;

                /*
                m_Sb.Append(e.OldFullPath);
                m_Sb.Append(" ");
                m_Sb.Append(e.ChangeType.ToString());
                m_Sb.Append(" ");
                m_Sb.Append("to ");
                m_Sb.Append(e.Name);
                m_Sb.Append("    ");
                m_Sb.Append(DateTime.Now.ToString());
                */

                if (rdbFile.Checked)
                {
                    m_Watcher.Filter = e.Name;
                    m_Watcher.Path = e.FullPath.Substring(0, e.FullPath.Length - m_Watcher.Filter.Length);
                }

            }
        }

        private void tmrEditNotify_Tick(object sender, EventArgs e)
        {
            if (m_bDirty)
            {
                lock (Lock)
                {
                    lstNotification.BeginUpdate();

                    foreach (string sItem in m_strCol)
                    {
                        lstNotification.Items.Add(sItem);
                    }

                    lstNotification.EndUpdate();
                    m_strCol.Clear();

                    m_bDirty = false;
                }
            }
        }

        private void btnBrowseFile_Click(object sender, EventArgs e)
        {
            if (rdbDir.Checked)
            {
                DialogResult resDialog = dlgOpenDir.ShowDialog();
                if (resDialog.ToString() == "OK")
                {
                    txtFile.Text = dlgOpenDir.SelectedPath;
                }
            }
            else
            {
                DialogResult resDialog = dlgOpenFile.ShowDialog();
                if (resDialog.ToString() == "OK")
                {
                    txtFile.Text = dlgOpenFile.FileName;
                }
            }
        }

        private void btnLog_Click(object sender, EventArgs e)
        {
            DialogResult resDialog = dlgSaveFile.ShowDialog();
            if (resDialog.ToString() == "OK")
            {
                FileInfo fi = new FileInfo(dlgSaveFile.FileName);
                StreamWriter sw = fi.CreateText();
                foreach (string sItem in lstNotification.Items)
                {
                    sw.WriteLine(sItem);
                }
                sw.Close();
            }
        }

        private void rdbFile_CheckedChanged(object sender, EventArgs e)
        {
            if (rdbFile.Checked == true)
            {
                chkSubFolder.Enabled = false;
                chkSubFolder.Checked = false;
            }
        }

        private void rdbDir_CheckedChanged(object sender, EventArgs e)
        {
            if (rdbDir.Checked == true)
            {
                chkSubFolder.Enabled = true;
            }
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            lock (Lock)
            {
                lstNotification.BeginUpdate();
                lstNotification.Items.Clear();
                lstNotification.EndUpdate();

            }

        }

    }
}